package me.lwn.auth.security.web.authentication;

import me.lwn.auth.security.utils.LocalMessageSource;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.http.converter.OAuth2ErrorHttpMessageConverter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TokenAuthenticationFailureHandler implements AuthenticationFailureHandler {

    protected MessageSourceAccessor message = LocalMessageSource.getAccessor();
    private LoginLockedSupport loginLockedSupport;

    public void setLoginLocked(LoginLockedSupport loginLockedSupport) {
        this.loginLockedSupport = loginLockedSupport;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {

        HttpMessageConverter<OAuth2Error> errorHttpResponseConverter = new OAuth2ErrorHttpMessageConverter();
        OAuth2Error error;

        if (exception.getCause() instanceof BadCredentialsException) {
            error = new OAuth2Error("invalid_credentials", message.getMessage("TokenAuthenticationFailureHandler.badCredentials"), "");
        } else if (exception.getCause() instanceof LockedException) {
            error = new OAuth2Error("account_locked", message.getMessage("TokenAuthenticationFailureHandler.locked"), "");
        } else if (exception.getCause() instanceof BadSmsCodeException) {
            error = new OAuth2Error("invalid_sms_code", message.getMessage("TokenAuthenticationFailureHandler.badSmsCode", ""), "");
        } else {
            error = ((OAuth2AuthenticationException) exception).getError();
        }
        if (!(exception.getCause() instanceof LockedException)) {
            String username = StringUtils.hasText(request.getParameter("username")) ? request.getParameter("username") : request.getParameter("mobile");
            loginLockedSupport.count(request, response, username, error.getDescription());
        }
        ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response);
        httpResponse.setStatusCode(HttpStatus.BAD_REQUEST);
        errorHttpResponseConverter.write(error, null, httpResponse);
    }
}
